package com.xxh.blog.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxh.blog.dao.EssayDao;
import com.xxh.blog.entity.Essay;
import com.xxh.blog.entity.vo.EssayDetailVo;
import com.xxh.blog.entity.vo.EssayVo;
import com.xxh.blog.service.essayService;
import com.xxh.blog.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class essayServiceImpl extends ServiceImpl<EssayDao,Essay> implements essayService{

    @Autowired
    EssayDao essayDao;

    @Autowired
    RedisUtil redisUtil;

    /**
     * 参数1 分页信息
     * 参数2 查询条件：文章分类ID，置顶级别，查询的用户ID，是否精选,排序条件
     */
    @Override
    public IPage<EssayVo> paging(Page page, Integer cid, Integer level, Integer uid, Boolean recommend, String order){

        QueryWrapper<EssayVo> wrapper = new QueryWrapper<>();

        wrapper.eq(cid!=null,"category_id",cid)
                .eq(uid!=null,"user_id",uid)
                .eq(level!=null,"level",level)
                .orderByDesc(order!=null,order);
         //使用
         return essayDao.queryByCondition(page, wrapper);
    }

    /**
     *
     * @param page
     * @param id 文章ID
     * @return
     */
    @Override
    public EssayDetailVo selectDetail(Page page, Integer id) {
        QueryWrapper<EssayDetailVo> wrapper = new QueryWrapper<>();
        wrapper.eq(id!=null,"essay.id",id);
        return essayDao.getEssayDetail(page,wrapper);
    }

    /**
     * 初始化一周内的热点文章到缓存中
     */
    @Override
    public void initHotEssay() {

        //获取7天内所有文章
        List<Essay> list = this.list(new QueryWrapper<Essay>()
                .ge("created", DateUtil.lastWeek()));
        for(Essay essay:list){
            //文章创建时间：
            String key="day:rank:"+DateUtil.format(essay.getCreated(), DatePattern.PURE_DATE_FORMAT);
            //文章评论条数存到缓存，设置缓存过期时间
            redisUtil.zAdd(key, String.valueOf(essay.getId()),essay.getCommentCount());

            //设置key在文章创建的一周后过期
            redisUtil.expireAt(key,DateUtil.offsetWeek(essay.getCreated(),1));

            //缓存文章基本信息(文章的ID，文章标题，缓存过期时间)
            this.CacheIdAndTitel(essay,DateUtil.offsetWeek(essay.getCreated(),1));
        }
        //统计文章的评论数，并且存到redis
        this.zunionAndStore();
    }

    @Override
    public void incrCommentCountAndUnionWeekRank(Long essayid, boolean isinc) {
        String currentKey="day:rank:"+DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);

        Essay essay = this.getById(essayid);
        //缓存文章信息
        CacheIdAndTitel(essay,DateUtil.offsetWeek(new Date(),1));
        //评论数+1
        redisUtil.zIncrementScore(currentKey,String.valueOf(essayid),isinc?1:-1);
        //重算文章的总评论数，缓存到redis
        this.zunionAndStore();
    }

    /**
     * 新增阅读量
     * @param vo
     */
    @Override
    public void putViewCount(EssayDetailVo vo) {

        String key = "rank:essay:" + vo.getId();
        //缓存中获取阅读量
        Object o = redisUtil.hGet(key, "essay:viewcout");
        //没有就从实体获取阅读量+1()
        if(o==null){
            vo.setViewCount(vo.getViewCount() + 1);
        }else {
            Integer count = Integer.parseInt((String) o);
            vo.setViewCount(count + 1);
        }

        //设置阅读量到缓存
        redisUtil.hPut(key, "essay:viewcout", String.valueOf(vo.getViewCount()));
    }

    /**
     * 合并计算文章一周内的总评论数
     */
    private void zunionAndStore() {

        List<String> otherKeys=new ArrayList<>();
        for(int i=-6;i<0;i++){
            String tempkey="day:rank:"+DateUtil.format(DateUtil.offsetDay(new Date(),i), DatePattern.PURE_DATE_FORMAT);
            otherKeys.add(tempkey);
        }
        String desKey="week:rank";
        String curKey="day:rank:"+DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
        redisUtil.zUnionAndStore(curKey,otherKeys,desKey);

    }

    /**
     * 缓存七天内的文章基本信息
     * @param essay 文章内容
     * @param expireTime 缓存失效时间
     */
    private void CacheIdAndTitel(Essay essay,DateTime expireTime) {
        String key="rank:essay:"+essay.getId();
        redisUtil.hPutIfAbsent(key,"essay:title",essay.getTitle());
        redisUtil.hPutIfAbsent(key,"essay:ccount", String.valueOf(essay.getCommentCount()));
        redisUtil.hPutIfAbsent(key,"essay:id",String.valueOf(essay.getId()));
        redisUtil.hPutIfAbsent(key,"essay:viewcout",String.valueOf(essay.getViewCount()));
        redisUtil.expireAt(key,expireTime);
    }
}
